import { EventBus } from '/utils/event'
import { Storage } from '/utils/storage'
import { GlobalData } from '/store/state'
/** 事件总线 */
export const $event = new EventBus()
/** 日志管理器 */
export const $logger = wx.getLogManager({ level: 0 })

/** 含有过期时间的 storage */
export const $storage = new Storage({
  prefix: `${GlobalData.server}/`,
})

type ThrottleFn<T> = (this: T, ...rest: any[]) => void
interface DebounceFn {
  id?: number
  (...rest: any): void
}

/** 工具库 */
export const $utils = {
  /**
   * 获取列表最后一条数据的字段 默认为 `id`
   *
   * 一般用于加载更多时入参
   *
   * @param list 列表
   * @param [field=id] 字段，默认为 `id`
   * @returns 列表中最后一条数据的某字段值
   */
  getLastField(list: WechatMiniprogram.IAnyObject[], field = 'id') {
    const last = list[list.length - 1] || {}
    if (typeof last === 'object') {
      return last[field]
    } else {
      return last
    }
  },

  /**
   * 获取页面的分享路径 (携带 server 参数)
   *
   * @param path 要分享的目标地址, 如果不填则获取当前页面
   */
  getSharePath(path?: string) {
    if (!path) {
      const pages = getCurrentPages()
      const page = pages[pages.length - 1]
      const query = Object.keys(page.options)
        .map((k) => {
          if (k === 'server') return
          return `${k}=${page.options[k]}`
        })
        .join('&')
      path = `${page.route}?${query}&isShare=true`
    } else if (path.match(/server=/)) {
      return path
    }

    path += path.match(/\?/) ? '&' : '?'
    return path + `server=${GlobalData.server}`
  },

  /**
   * 节流函数
   *
   * 无论调用多少次回调方法, 在一定周期内只会执行一次
   *
   * @param fn 需要截流的方法
   * @param limit 周期 单位毫秒
   */
  throttle<T>(this: T, fn: ThrottleFn<T>, limit: number): ThrottleFn<T> {
    let timer: any
    let lastRun: number

    return function (...args: any[]) {
      if (!lastRun) {
        fn.apply(this, args)
        lastRun = Date.now()
      } else {
        clearTimeout(timer)
        timer = setTimeout(() => {
          if (Date.now() - lastRun >= limit) {
            fn.apply(this, args)
            lastRun = Date.now()
          }
        }, limit - (Date.now() - lastRun))
      }
    }
  },

  /**
   * 防抖函数
   *
   * @param {DebounceFn} fn
   * @param {number} delay
   */
  debounce(fn: DebounceFn | any, delay: number) {
    return function (this: any, ...args: any[]) {
      clearTimeout(fn.id!)
      fn.id = setTimeout(() => {
        fn.apply(this, args)
      }, delay)
    }
  },

  /** 将 query string 转化为对象 */
  parseQueryString(str: string): Record<string, string> {
    return JSON.parse(
      '{"' +
      decodeURIComponent(str).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"') +
      '"}',
    )
  },

  /** 将网络图片转化为本地图片地址 */
  getImageInfo(
    src: string,
    query?: string,
  ): Promise<WechatMiniprogram.GetImageInfoSuccessCallbackResult> {
    return new Promise((resolve, reject) => {
      if (!src) return resolve({ path: '' } as WechatMiniprogram.GetImageInfoSuccessCallbackResult)
      if (query) src += `?${query}`
      wx.getImageInfo({
        src,
        success: resolve,
        fail: reject,
      })
    })
  },

  /** 弹出 ActionSheet */
  showActionSheets(actions: ActionSheet[]) {
    wx.showActionSheet({
      itemList: actions.map((i) => i.label),
      success: (res) => {
        actions[res.tapIndex].method()
      },
    })
  },
}
